﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Styx;
using System.Threading;
using System.Windows.Media;
using Styx.Common;
using Styx.Common.Helpers;
using Styx.CommonBot;
using Styx.CommonBot.POI;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.Pathing;
using Styx.Plugins;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using System.Diagnostics;
using Action = Styx.TreeSharp.Action;
using Styx.TreeSharp;

namespace Boogman
{
    public partial class Main : CombatRoutine
    {
        private static Stopwatch petPresenceTimer = new Stopwatch();
        private static Stopwatch dismountTimer = new Stopwatch();
        private static Stopwatch MoveBackTimer = new Stopwatch();
        private static Stopwatch RapidFireTimer = new Stopwatch();
        private static Stopwatch ReadinessTimer = new Stopwatch();

        public int Misdirection = 34477;
        public int SerpentSting = 1978;
        public int ExplosiveShot = 53301;
        public int CobraShot = 77767;
        public int ArcaneShot = 3044;
        public int MultiShot = 2643;
        public int KillShot = 53351;
        public int BlackArrow = 3674;
        public int MurderOfCrows = 131894;
        public int SilencingShot = 34490;
        public int FeignDeath = 5384;
        public int RapidFire = 3045;
        public int Disengage = 781;
        public int Deterrence = 19263;
        public int ConcussiveShot = 5116;
        public int TrapLauncher = 77769;
        public int FreezingTrap = 60192;
        public int ExplosiveTrap = 82939;
        public int SnakeTrap = 82948;
        public int IceTrap = 82941;
        public int StoneForm = 20894;
        public int Camouflage = 51753;
        public int RevivePet = 982;
        public int MendPet = 136;
        public int MastersCall = 53271;
        public int HuntersMark = 1130;
        public int Flare = 1543;
        public int Readiness = 23989;
        public int Stampede = 121818;
        public int DireBeast = 120679;
        public int AspectIronHawk = 109260;
        public int AspectHawk = 13165;
        public int GlaiveToss = 117050;
        public int ScatterShot = 19503;
        public int SteadyShot = 56641;
        public int WidowVenom = 82654;
        public int TranquilizingShot = 19801;
        public int LockAndLoad = 56453;
        public int BloodFury = 20572;
        public int Berserking = 26297;
        public int Lifeblood = 121279;
        public int RecentlyBandaged = 11196;

        public string useSpell(int spell)
        {
            string mySpell = "";

            switch (spell)
            {
                case 56453: mySpell = "Lock and Load"; break;
                case 19801: mySpell = "Tranquilizing Shot"; break;
                case 82654: mySpell = "Widow Venom"; break;
                case 19503: mySpell = "Scatter Shot"; break;
                case 117050: mySpell = "Glaive Toss"; break;
                case 109260: mySpell = "Aspect of the Iron Hawk"; break;
                case 120679: mySpell = "Dire Beast"; break;
                case 121818: mySpell = "Stampede"; break;
                case 23989: mySpell = "Readiness"; break;
                case 34477: mySpell = "Misdirection"; break;
                case 1978: mySpell = "Serpent Sting"; break;
                case 53301: mySpell = "Explosive Shot"; break;
                case 77767: mySpell = "Cobra Shot"; break;
                case 3044: mySpell = "Arcane Shot"; break;
                case 2343: mySpell = "Multi-Shot"; break;
                case 53351: mySpell = "Kill Shot"; break;
                case 3674: mySpell = "Black Arrow"; break;
                case 131894: mySpell = "A Murder of Crows"; break;
                case 34490: mySpell = "Silencing Shot"; break;
                case 5384: mySpell = "Feign Death"; break;
                case 3045: mySpell = "Rapid Fire"; break;
                case 781: mySpell = "Disengage"; break;
                case 19263: mySpell = "Deterrence"; break;
                case 5116: mySpell = "Concussive Shot"; break;
                case 77769: mySpell = "Trap Launcher"; break;
                case 60192: mySpell = "Freezing Trap"; break;
                case 82939: mySpell = "Explosive Trap"; break;
                case 82948: mySpell = "Snake Trap"; break;
                case 82941: mySpell = "Ice Trap"; break;
                case 20894: mySpell = "Stone Form"; break;
                case 51753: mySpell = "Camouflage"; break;
                case 982: mySpell = "Revive Pet"; break;
                case 136: mySpell = "Mend Pet"; break;
                case 53271: mySpell = "Master's Call"; break;
                case 1130: mySpell = " Hunter's Mark"; break;
                case 1543: mySpell = "Flare"; break;
                case 20572: mySpell = "Blood Fury"; break;
                case 26297: mySpell = "Berserking"; break;
                case 56641: mySpell = "Steady Shot"; break;
            }
            return mySpell;
        }

        public string HavePotionBuff = "";
        public string HaveFlaskBuff = "";
        public string HaveHealPotions = "";
        public string HaveLifeSpirit = "";
        public string HaveHealthStone = "";
        public string HaveBandages = "";
        public string LastSpell = "";
         
        public bool UseTrapLauncer()
        {
            if (SpellManager.HasSpell(TrapLauncher)
                && !buffExists(TrapLauncher, Me))
            {
                if (SpellManager.CanCast(TrapLauncher))
                {
                    SpellManager.Cast(TrapLauncher);
                    LogMsg("Trap Launcher", 2);
                    return true;
                }
            }
            return false;
        }
        public bool UseAspect()
        {
            if(SpellManager.HasSpell(AspectIronHawk)
                && !buffExists(AspectIronHawk, Me))
            {
                if (SpellManager.CanCast(AspectIronHawk))
                {
                    SpellManager.Cast(AspectIronHawk);
                    LogMsg("Aspect of the Iron Hawk", 2);
                    return true;
                }
            }
            if (!SpellManager.HasSpell(AspectIronHawk)
                && !buffExists(AspectHawk, Me))
            {
                if (SpellManager.CanCast(AspectHawk))
                {
                    SpellManager.Cast(AspectHawk);
                    LogMsg("Aspect of the Hawk", 2);
                    return true;
                }
            }
            return false;
        }
        public bool UseMendPet()
        {
            if (gotTarget
                && SpellManager.HasSpell(MendPet)
                && !buffExists(MendPet, Me.Pet)
                && Me.Pet != null
                && Me.GotAlivePet
                && Me.Pet.HealthPercent <= BoogmanSettings.myPrefs.mendpetpercent)
            {
                if (SpellManager.CanCast(MendPet))
                {
                    SpellManager.Cast(MendPet);
                    LogMsg("Mend Pet", 2);
                    return true;
                }
            }
            return false;
        }
        public void UseTrinket1()
        {
            if (Me.CurrentTarget != null
                && Me.CurrentTarget.IsAlive
                && Me.Combat)
            {

                var firstTrinket = StyxWoW.Me.Inventory.Equipped.Trinket1;
                if (BoogmanSettings.myPrefs.trinket1 == 2
                    && IsBoss)
                {

                    if (firstTrinket != null && CanUseEquippedItem(firstTrinket))
                    {
                        firstTrinket.Use();
                        LogMsg("Using 1st trinket", 2);
                    }
                }
                if (BoogmanSettings.myPrefs.trinket1 == 1)
                {
                    if (firstTrinket != null && CanUseEquippedItem(firstTrinket))
                    {
                        firstTrinket.Use();
                        LogMsg("Using 1st trinket", 2);
                    }
                }
            }
        }
        public void UseTrinket2()
        {

            if (Me.CurrentTarget != null
                && Me.CurrentTarget.IsAlive
                && Me.Combat)
            {
                var secondTrinket = StyxWoW.Me.Inventory.Equipped.Trinket2;


                if (BoogmanSettings.myPrefs.trinket2 == 2
                    && IsBoss)
                {

                    if (secondTrinket != null && CanUseEquippedItem(secondTrinket))
                    {
                        secondTrinket.Use();
                        LogMsg("Using 2nd trinket", 2);
                    }
                }
                else if (BoogmanSettings.myPrefs.trinket2 == 1)
                {
                    if (secondTrinket != null && CanUseEquippedItem(secondTrinket))
                    {
                        secondTrinket.Use();
                        LogMsg("Using 2nd trinket", 2);
                    }
                }
            }
        }
        public void UseEngiGloves()
        {

            if (Me.CurrentTarget != null
                && Me.CurrentTarget.IsAlive
                && Me.Combat)
            {
                var engiGloves = StyxWoW.Me.Inventory.Equipped.Hands;

                if (BoogmanSettings.myPrefs.engigloves == 2
                    && IsBoss)
                {
                    if (engiGloves != null && CanUseEquippedItem(engiGloves))
                    {
                        engiGloves.Use();
                        LogMsg("Using Engineer Gloves", 2);
                    }
                }
                else if (BoogmanSettings.myPrefs.engigloves == 1)
                {
                    if (engiGloves != null && CanUseEquippedItem(engiGloves))
                    {
                        engiGloves.Use();
                        LogMsg("Using Engineer Gloves", 2);
                    }
                }
            }
        }


        public void NeedMisdirection()
        {
            if (Me.CurrentTarget != null
                && Me.CurrentTarget.IsAlive
                && BoogmanSettings.myPrefs.misdirection == 1
                && !buffExists(Misdirection, Me)
                && Me.CurrentTarget.ThreatInfo.RawPercent > 75
                && !spellOnCooldown(Misdirection)
                && !UseAoe)
            {
                Lua.DoString("RunMacroText('/cast [@focus,help][help][@pet,exists] Misdirection');");
                {
                    LogMsg(">> Misdirection on Aggro ! <<", 0);
                }
            }
            if (gotTarget
                && BoogmanSettings.myPrefs.misdirection == 1
                && (!Me.GroupInfo.IsInRaid || !Me.IsInInstance)
                && !buffExists(Misdirection, Me)
                && !spellOnCooldown(Misdirection)
                && UseAoe)
            {
                Lua.DoString("RunMacroText('/cast [@focus,help][help][@pet,exists] Misdirection');");
                {
                    LogMsg(">> Misdirection Aoe <<", 0);
                }
            }
        }
        #region pause

        public bool Paused = false;

        public override void ShutDown()
        {
            Lua.Events.DetachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
        }

        private void HandleModifierStateChanged(object sender, LuaEventArgs args)
        {
            if (BoogmanSettings.myPrefs.PauseKeys == BoogmanSettings.Keypress.None)
            {
                return;
            }

            if (Convert.ToInt32(args.Args[1]) == 1)
            {
                if (args.Args[0].ToString() == BoogmanSettings.myPrefs.PauseKeys.ToString())
                {
                    Paused = !Paused;
                    if (Paused)
                    {
                        Logging.Write("Aoe turned off, press {0} in WOW again to turn back on",
                                     BoogmanSettings.myPrefs.PauseKeys.ToString());
                        if (BoogmanSettings.myPrefs.PrintMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"Aoe Turned off\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                    else
                    {
                        Logging.Write("Turning Aoe back on");
                        if (BoogmanSettings.myPrefs.PrintMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"Aoe turned on\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                }
            }
        }
        #endregion pause

        private static bool CanUseEquippedItem(WoWItem item)
        {
            // Check for engineering tinkers!
            string itemSpell = Lua.GetReturnVal<string>("return GetItemSpell(" + item.Entry + ")", 0);
            if (string.IsNullOrEmpty(itemSpell))
                return false;


            return item.Usable && item.Cooldown <= 0;
        }

        #region logs
        public void LogMsg(string msg, int kleurtje)
        {
            Color kleur = Colors.Yellow;
            switch (kleurtje)
            {
                case 0:
                    kleur = Colors.Orange;
                    break;
                case 1:
                    kleur = Colors.PaleGreen;
                    break;
                case 2:
                    kleur = Colors.BlanchedAlmond;
                    break;
                case 3:
                    kleur = Colors.Yellow;
                    break;
                case 4:
                    kleur = Colors.Red;
                    break;
                case 5:
                    kleur = Colors.Crimson;
                    break;
                case 6:
                    kleur = Colors.LightBlue;
                    break;
                case 7:
                    kleur = Colors.Cyan;
                    break;
                case 8:
                    kleur = Colors.DarkSeaGreen; // TotH
                    break;
                case 9:
                    kleur = Colors.ForestGreen; //Lock and load
                    break;
                case 10:
                    kleur = Colors.DeepSkyBlue; //focusdump
                    break;
            }
            Logging.Write(kleur, msg);
            LastSpell = msg;
        }
        #endregion logs

        #region AddCounting
        private int addCount
        {
            get
            {
                int count = 0;
                foreach (WoWUnit u in ObjectManager.GetObjectsOfType<WoWUnit>(true, true))
                {
                    if (Me.CurrentTarget != null
                        && u.CanSelect
                        && !u.IsPlayer
                        && u.IsAlive
                        && u.Guid != Me.Guid
                        && !u.IsFriendly
                        && u.IsHostile
                        && u.Attackable
                        && !u.IsTotem
                        && !u.IsCritter
                        && !u.IsNonCombatPet
                        && (u.Location.Distance(Me.CurrentTarget.Location) <= 10 || u.Location.Distance2D(Me.CurrentTarget.Location) <= 10))
                    {
                        count++;
                    }
                }
                return count;
            }
        }
        #endregion AddCounting

        #region Kind of target
        public bool IsBoss
        {
            get
            {
                if (Me.CurrentTarget != null
                    && Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.WorldBoss)
                {
                    return true;
                }
                else if (Me.CurrentTarget != null
                    && target.IsBoss(Me.CurrentTarget))
                {
                    return true;
                }
                else if (Me.CurrentTarget != null
                    && Me.CurrentTarget.MaxHealth >= (65 * 1000000))
                {
                    return true;
                }
                else if (Me.CurrentTarget != null
                    && Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.Elite
                    && Me.CurrentTarget.MaxHealth >= (Me.MaxHealth * 4)
                    && !Me.GroupInfo.IsInParty
                    && !Me.IsInInstance
                    && !Me.GroupInfo.IsInRaid)
                {
                    return true;
                }
                else if (Me.CurrentTarget != null
                    && Me.CurrentTarget.IsAlive
                    && Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.Rare
                    && Me.CurrentTarget.MaxHealth >= (Me.MaxHealth * 4))
                {
                    return true;
                }
                else if (Me.CurrentTarget != null
                    && Me.CurrentTarget.Name.Contains("Training Dummy")
                    && !Me.IsInInstance)
                {
                    return true;
                }
                else if (Me.CurrentTarget != null
                    && Me.CurrentTarget.IsPlayer
                    && !Me.CurrentTarget.IsFriendly)
                {
                    return true;
                }
                return false;
            }
        }

        #endregion Kind of Target
        #region Pet
        public void CallPet()
        {
            if (BoogmanSettings.myPrefs.autocallrevivepet == 1
                && !Me.Mounted
                && !Me.IsFlying
                && !Me.OnTaxi
                && !Me.IsGhost
                && (Me.Pet == null
                || !Me.GotAlivePet)
                && !buffExists(FeignDeath, Me))
            {
                string myPet = "Call Pet " + BoogmanSettings.myPrefs.callpetnr;
                if (SpellManager.CanCast(myPet)
                    && LastSpell != "CallPet"
                    && !Me.IsCasting)
                {
                    SpellManager.Cast(myPet);
                    Logging.Write(Colors.PaleGreen, myPet);
                    petPresenceTimer.Restart();
                    LastSpell = "CallPet";
                }
            }
            return;
        }
        public void ReviveMyPet()
        {
            if (BoogmanSettings.myPrefs.autocallrevivepet == 1
                && !Me.Mounted
                && !Me.IsGhost
                && !Me.IsFlying
                && !Me.OnTaxi
                && !buffExists(FeignDeath, Me)
                && petPresenceTimer.Elapsed.Seconds > 3)
            { 
                    if (SpellManager.CanCast("Revive Pet"))
                    {
                        SpellManager.Cast("Revive Pet");
                        Logging.Write(Colors.PaleGreen, "RevivePet");
                        petPresenceTimer.Reset();
                        LastSpell = "RevivePet";
                    }
            }
            return;
        }
        #endregion pet

        #region dismount
        
        #endregion dismount

        public bool FlaskBuff()
        {
            if (Me.HasAura("Flask of the Warm Sun")) { return true; }
            if (Me.HasAura("Flask of Winter's Bite")) { return true; }
            if (Me.HasAura("Flask of the Earth")) { return true; }
            if (Me.HasAura("Flask of Spring Blossoms")) { return true; }
            if (Me.HasAura("Flask of Falling Leaves")) { return true; }
            /*if (Me.HasAura("Flask of the Winds")) { return true; }
            if (Me.HasAura("Flask of Titanic Strenght")) { return true; }
            if (Me.HasAura("Flask of the Draconic Mind")) { return true; }
            if (Me.HasAura("Flask of Flowing Water")) { return true; }
            if (Me.HasAura("Flask of Steelskin")) { return true; }
            if (Me.HasAura("Flask of Endless Rage")) { return true; }
            if (Me.HasAura("Flask of Pure Mojo")) { return true; }
            if (Me.HasAura("Flask of Stoneblood")) { return true; }
            if (Me.HasAura("Flask of the Frost Wyrm")) { return true; }
            if (Me.HasAura("Flask of Toughness")) { return true; }
            if (Me.HasAura("Flask of Binding Light")) { return true; }*/
            return false;
        }
        public void AlchemistFlask()
        {
            if (BoogmanSettings.myPrefs.alchemyflask == 1)
            {

                if (!Me.HasAura("Enhanced Agility") && !FlaskBuff() && !Me.Mounted)
                {
                    foreach (WoWItem item in Me.BagItems)
                    {
                        if (item != null)
                        {
                            if (item.Name == "Alchemist's Flask")
                            {
                                Lua.DoString("RunMacroText(\"/use " + item.Name + "\")");
                                Logging.Write(Colors.LightBlue, "Using Alchemist's Flask");
                                break;
                            }
                        }
                    }
                }
            }
        }
        public void myPotion()
        {
            if (Me.CurrentTarget != null
                    && Me.Combat
                    && BoogmanSettings.myPrefs.virmenpotion == 1)
            {
                WoWItem potion = Me.BagItems.FirstOrDefault(h => h.Entry == 76089);

                if (potion == null
                    && HavePotionBuff != "no")
                {
                    Logging.Write(Colors.BlanchedAlmond, "I have no Agility Potion");
                    HavePotionBuff = "no";
                }
                if (potion != null && potion.CooldownTimeLeft.TotalMilliseconds <= 0)
                {
                    potion.Use();
                    Logging.Write(Colors.BlanchedAlmond, "Using Agility Potion");
                    HavePotionBuff = "yes";
                }
            }
        }
        public void HealthStone()
        {
            if (Me.Combat
                && Me.HealthPercent <= BoogmanSettings.myPrefs.healthstonepercent)
            {
                WoWItem hstone = Me.BagItems.FirstOrDefault(h => h.Entry == 5512);
                if (hstone == null
                    && HaveHealthStone != "no")
                {
                    Logging.Write(Colors.BlanchedAlmond, "I have no Healthstone");
                    HaveHealthStone = "no";
                    return;
                }
                if (hstone != null && hstone.CooldownTimeLeft.TotalMilliseconds <= 0)
                {
                    hstone.Use();
                    Logging.Write(Colors.BlanchedAlmond, "Using Healthstone");
                    HaveHealthStone = "yes";
                }
            }
        }
        public void myFlask()
        {
            bool useFlask = false;

            if (BoogmanSettings.myPrefs.agilityflask == 1) { useFlask = true; }

            if (Me.Combat
                && useFlask
                && !FlaskBuff())
            {
                WoWItem flask = Me.BagItems.FirstOrDefault(h => h.Entry == 76084);
                if (flask == null
                    && HaveFlaskBuff != "no")
                {
                    Logging.Write(Colors.BlanchedAlmond, "I have no Agility Flask");
                    HaveFlaskBuff = "no";
                }
                if (flask != null && flask.CooldownTimeLeft.TotalMilliseconds <= 0)
                {
                    flask.Use();
                    Logging.Write(Colors.BlanchedAlmond, "Using Agility Flask");
                    HaveFlaskBuff = "yes";
                }
            }
        }
        #region cooldowns
        public bool lifeblood
        {
            get
            {
                if (BoogmanSettings.myPrefs.lifeblood == 1
                    && Me.CurrentTarget.HealthPercent > 25
                    && !Me.HasAura("Bloodlust")
                    && !Me.HasAura("Heroism")
                    && !Me.HasAura("Time Warp"))
                {
                    return true;
                }
                if (BoogmanSettings.myPrefs.lifeblood == 2
                    && Me.CurrentTarget.HealthPercent >= 5
                    && !Me.HasAura("Bloodlust")
                    && !Me.HasAura("Heroism")
                    && !Me.HasAura("Time Warp")
                    && IsBoss)
                {
                    return true;
                }
                return false;
            }
        }
        public bool Crows
        {
            get
            {
                if (BoogmanSettings.myPrefs.murderofcrows == 1
                    && Me.CurrentTarget.HealthPercent > 25) { return true; }
                if (BoogmanSettings.myPrefs.murderofcrows == 2 && IsBoss
                    && Me.CurrentTarget.HealthPercent >= 5) { return true; }
                return false;
            }
        }
        public bool Stamp
        {
            get
            {
                if (BoogmanSettings.myPrefs.stampede == 1
                    && Me.CurrentTarget.HealthPercent > 25) { return true; }
                if (BoogmanSettings.myPrefs.stampede == 2 && IsBoss
                    && Me.CurrentTarget.HealthPercent >= 5) { return true; }
                return false;
            }
        }

        public bool Bloodfury
        {
            get
            {
                if (BoogmanSettings.myPrefs.bloodfury == 1
                    && Me.CurrentTarget.HealthPercent > 25) { return true; }
                if (BoogmanSettings.myPrefs.bloodfury == 2 && IsBoss
                    && Me.CurrentTarget.HealthPercent >= 5) { return true; }
                return false;
            }
        }
        public bool berserKing
        {
            get
            {
                if (BoogmanSettings.myPrefs.berserking == 1
                    && Me.CurrentTarget.HealthPercent > 25
                    && !Me.HasAura("Bloodlust")
                    && !Me.HasAura("Heroism")
                    && !Me.HasAura("Time Warp")) 
                { 
                    return true;
                }
                if (BoogmanSettings.myPrefs.berserking == 2
                    && Me.CurrentTarget.HealthPercent >= 5
                    && !Me.HasAura("Bloodlust")
                    && !Me.HasAura("Heroism")
                    && !Me.HasAura("Time Warp")
                    && IsBoss) 
                { 
                    return true; 
                }
                return false;
            }
        }
        public bool Rapidfire
        {
            get
            {
                if (BoogmanSettings.myPrefs.rapidfire == 1
                    && Me.CurrentTarget.HealthPercent > 25) 
                {
                    RapidFireTimer.Restart();
                    return true; 
                }
                if (BoogmanSettings.myPrefs.rapidfire == 2 && IsBoss
                    && Me.CurrentTarget.HealthPercent >= 5) 
                {
                    RapidFireTimer.Restart();
                    return true; 
                }
                return false;
            }
        }
        public bool myTargetDistance
        {
            get
            {
                if (targetDistance(Me.CurrentTarget) <= 40 * 40)
                {
                    return true;
                }
                return false;
            }
        }
        #endregion cooldowns

        public bool UseSpells
        {
            get
            {
                if (Me.Mounted
                    || Me.IsGhost
                    || Me.IsDead
                    || Me.OnTaxi
                    || Me.IsFlying)
                {
                    return false;
                }
                return true;
            }
        }
        #region targettest
        public static void EnsureTarget()
        {
            if (StyxWoW.Me.IsInInstance &&
                TankManager.TargetingTimer.IsFinished && StyxWoW.Me.Combat && TankManager.Instance.FirstUnit != null &&
                (StyxWoW.Me.CurrentTarget == null || StyxWoW.Me.CurrentTarget != TankManager.Instance.FirstUnit))
            {
                Logging.Write("Targeting first unit of TankTargeting");
                TankManager.Instance.FirstUnit.Target();
                TankManager.TargetingTimer.Reset();
            }

            WoWObject ctx = GatherTarget();
            if (ctx != null)
            {
                Logging.Write("Current target is not the best target. Switching to " + ctx + "!");
                ((WoWUnit)ctx).Target();
            }

            if (StyxWoW.Me.CurrentTarget == null || StyxWoW.Me.CurrentTarget.IsDead)
            {
                ctx = GatherTarget2();
                if (ctx != null)
                {
                    Logging.Write("Currect target is invalid. Switching to " + ctx + "!");
                    ((WoWUnit)ctx).Target();
                }
            }
        }

        private static WoWObject GatherTarget2()
        {
            // If we have a RaF leader, then use its target.
            var rafLeader = RaFHelper.Leader;
            if (rafLeader != null && rafLeader.IsValid && !rafLeader.IsMe && rafLeader.Combat &&
                rafLeader.CurrentTarget != null && rafLeader.CurrentTarget.IsAlive && !Blacklist.Contains(rafLeader.CurrentTarget))
            {
                return rafLeader;
            }

            // Check bot poi.
            if (BotPoi.Current.Type == PoiType.Kill)
            {
                var unit = BotPoi.Current.AsObject as WoWUnit;

                if (unit != null && unit.IsAlive && !unit.IsMe && !Blacklist.Contains(unit))
                {
                    return unit;
                }
            }

            // Does the target list have anything in it? And is the unit in combat?
            // Make sure we only check target combat, if we're NOT in a BG. (Inside BGs, all targets are valid!!)
            var firstUnit = Targeting.Instance.FirstUnit;
            if (firstUnit != null && firstUnit.IsAlive && !firstUnit.IsMe && firstUnit.Combat &&
                !Blacklist.Contains(firstUnit))
            {
                return firstUnit;
            }

            // Cache this query, since we'll be using it for 2 checks. No need to re-query it.
            var agroMob =
                ObjectManager.GetObjectsOfType<WoWUnit>(false, false).
                    Where(p => !Blacklist.Contains(p) && p.IsHostile && !p.IsOnTransport && !p.IsDead &&
                                !p.Mounted && p.DistanceSqr <= 70 * 70 && p.Combat).
                    OrderBy(u => u.DistanceSqr).
                    FirstOrDefault();

            if (agroMob != null)
            {
                // Return the closest one to us
                return agroMob;
            }

            // And there's nothing left, so just return null, kthx.
            return null;
        }

        private static WoWObject GatherTarget()
        {
            // No target switching for tanks. They check for their own stuff above.
            if (StyxWoW.Me.IsInInstance)
                return null;
            // Go below if current target is null or dead. We have other checks to deal with that
            if (StyxWoW.Me.CurrentTarget == null || StyxWoW.Me.CurrentTarget.IsDead)
                return null;
            // If the current target is in combat or has aggro towards us, it should be a valid target.
            if (StyxWoW.Me.CurrentTarget != null && (StyxWoW.Me.CurrentTarget.Combat || StyxWoW.Me.CurrentTarget.Aggro))
                return null;
            if (BotPoi.Current.Type == PoiType.Kill)
            {
                var obj = BotPoi.Current.AsObject;

                if (obj != null)
                {
                    if (StyxWoW.Me.CurrentTarget != obj)
                        return obj;
                }
            }
            // Make sure we have the proper target from Targeting. 
            // The Botbase should give us the best target in targeting.
            var firstUnit = Targeting.Instance.FirstUnit;

            if (firstUnit != null)
            {
                if (StyxWoW.Me.CurrentTarget != firstUnit)
                    return firstUnit;
            }
            return null;
        }
        public float MeleeRange
        {
            get
            {
                if (StyxWoW.Me.CurrentTargetGuid == 0)
                    return 0f;

                if (StyxWoW.Me.CurrentTarget.IsPlayer)
                    return 3.5f;

                return Math.Max(5f, StyxWoW.Me.CombatReach + 1.3333334f + StyxWoW.Me.CurrentTarget.CombatReach);
            }
        }
        #endregion

        #region Movement
        public void MoveInRange(float dist)
        {
            if (Me.CurrentTarget != null
                && !BoogmanSettings.myPrefs.DisableMovement)
            {
                float range = dist;
                while (Me.CurrentTarget != null
                    && StyxWoW.Me.Location.Distance(StyxWoW.Me.CurrentTarget.Location) > range)
                {
                    Navigator.MoveTo(StyxWoW.Me.CurrentTarget.Location);
                };
                Navigator.PlayerMover.MoveStop();
            }

        }
        public void MoveInLignOfSight()
        {
            if (Me.GotTarget
                && !Me.CurrentTarget.InLineOfSight
                && !BoogmanSettings.myPrefs.DisableMovement)
            {
                while (!Me.CurrentTarget.InLineOfSight)
                {
                    Navigator.MoveTo(StyxWoW.Me.CurrentTarget.Location);
                }
                Navigator.PlayerMover.MoveStop();
            }
        }
        public void MoveBack(WoWMovement.MovementDirection direction)
        {
            MoveBackTimer.Start();

            while (MoveBackTimer.Elapsed.Seconds != 1)
            {
                WoWMovement.Move(direction);
            }

            Navigator.PlayerMover.MoveStop();
            MoveBackTimer.Reset();
        }
        public void MoveBackwards()
        {
            if (!BoogmanSettings.myPrefs.DisableMovement
                && Me.CurrentTarget != null
                && Me.CurrentTarget.Distance < 8)
            {
                MoveBack(WoWMovement.MovementDirection.Backwards);
            }
        }
        #endregion Movement

        #region facing
        public void Facing()
        {
            if (gotTarget
                && !BoogmanSettings.myPrefs.DisableFacing)
            {
                Me.CurrentTarget.Face();
            }
        }
        #endregion facing


        public void TakingPetTarget()
        {
            if (!BoogmanSettings.myPrefs.DisableTargetting
                && !Me.GotTarget
                && Me.Pet != null
                && (Me.Pet.Combat
                || Me.PetAggro))
            {
                if (Me.Pet.CurrentTarget != null)
                {
                    Me.Pet.CurrentTarget.Target();
                    Facing();
                    MoveInRange(35);
                    SpellManager.Cast(ArcaneShot);
                    LogMsg("Taking pet's target", 1);
                    LogMsg("Arcane Shot", 6);
                    Lua.DoString("StartAttack()");
                }
            }
        }
        public bool UseAoe
        {
            get
            {
                if (gotTarget
                    && SpellManager.HasSpell(MultiShot)
                    && !Paused
                    && addCount >= BoogmanSettings.myPrefs.startaoe)
                {
                    return true;
                }
                return false;
            }
        }
        
        public bool PetAttack()
        { 
            if (Me.Combat
                 && gotTarget
                 && !Me.Pet.IsAutoAttacking)
            {
                 Lua.DoString("PetAttack()");
            }

            return false;
        }


        #region bandages

        public void UseBandages()
        {
            if (!Me.Combat
                && !buffExists(RecentlyBandaged, Me)
                && Me.HealthPercent <= BoogmanSettings.myPrefs.UseBandages
                && myBandages != 0)
            {
                int useBandage = myBandages;

                WoWItem bandage = Me.BagItems.FirstOrDefault(h => h.Entry == useBandage);
                if (bandage == null
                    && HaveBandages != "no")
                {
                    Logging.Write(Colors.BlanchedAlmond, "I have no Bandages");
                    HaveBandages = "no";
                    return;
                }
                if (bandage != null && bandage.CooldownTimeLeft.TotalMilliseconds <= 0)
                {
                    bandage.Use();
                    Logging.Write(Colors.BlanchedAlmond, "Using " + bandage.Name);
                    HaveBandages = "yes";
                }
            }
            return;
        }

        public int myBandages
        {
            get
            {
                WoWItem RuneCloth = Me.BagItems.FirstOrDefault(h => h.Entry == 14529);
                if (RuneCloth != null)
                {
                    return 14529;
                }
                WoWItem HeavyMageWeave = Me.BagItems.FirstOrDefault(h => h.Entry == 8545);
                if (HeavyMageWeave != null)
                {
                    return 8545;
                }
                WoWItem MageWeave = Me.BagItems.FirstOrDefault(h => h.Entry == 8544);
                if (MageWeave != null)
                {
                    return 8544;
                }
                WoWItem HeavySilk = Me.BagItems.FirstOrDefault(h => h.Entry == 6451);
                if (HeavySilk != null)
                {
                    return 6451;
                }
                WoWItem Silk = Me.BagItems.FirstOrDefault(h => h.Entry == 6450);
                if (Silk != null)
                {
                    return 6450;
                }
                WoWItem HeavyWool = Me.BagItems.FirstOrDefault(h => h.Entry == 3531);
                if (HeavyWool != null)
                {
                    return 3531;
                }
                WoWItem Wool = Me.BagItems.FirstOrDefault(h => h.Entry == 3530);
                if (Wool != null)
                {
                    return 3530;
                }
                WoWItem HeavyLinen = Me.BagItems.FirstOrDefault(h => h.Entry == 2581);
                if (HeavyLinen != null)
                {
                    return 2581;
                }
                WoWItem Linen = Me.BagItems.FirstOrDefault(h => h.Entry == 1251);
                if (Linen != null)
                {
                    return 1251;
                }
                return 0;
            }
        }

        #endregion bandages
    }
}

